import { _decorator, Component, Node, Vec3, RigidBody, Quat, CameraComponent, find } from 'cc';
import { EventMgr } from '../../../Framework/Scripts/Managers/EventMgr';
import { poolManager } from '../../../Framework/Scripts/Managers/poolManager';
import { ResMgr } from '../../../Framework/Scripts/Managers/ResMgr';
import { SoundMgr } from '../../../Framework/Scripts/Managers/SoundMgr';
import { TimerMgr } from '../../../Framework/Scripts/Managers/TimerMgr';
import { UIMgr } from '../../../Framework/Scripts/Managers/UIMgr';
import myUtil from '../../../Framework/Scripts/Utils/myUtil';
import { constant, OBJ_TYPE, playParticleOptions, RangeType } from '../constant';
import { GameApp } from '../GameApp';
import { enemyBase } from './enemyBase';
import { MonsterBloodBar } from './fight/monsterBloodBar';
import { PlayerModel } from './player/playerModel';
const { ccclass, property } = _decorator;
let v3_tipsOffsetPos = new Vec3(-50, 175, 0);//血条距离小怪节点位置
let v3_monsterBloodOffsetPos = new Vec3(0, 150, 0);//血条距离小怪节点位置
let v3_monsterBloodScale = new Vec3(1, 1, 1);//小怪血条缩放大小




/** 
  周无邪出品
  本源码用于学习研究使用。
  作者联系方式：tuya7078（微信）。
 */

@ccclass('playerBase')
export class playerBase extends Component {


    @property({ displayName: "行走动画" })
    protected walkAni: string = "run"

    @property({ displayName: "攻击动画1" })
    protected attackAni1: string = "attack"

    @property({ displayName: "攻击动画2" })
    protected attackAni2: string = "attack2"

    @property({ displayName: "死亡动画" })
    protected dieAni: string = "die"

    @property({ displayName: "站立动画" })
    protected idelAni: string = "idle"
    @property({ type: Number, displayName: "移动速度" })
    protected mSpeed: number = 400;//移动速度

    @property({ type: Number, displayName: "生命值" })
    protected hp: number = 850;//生命值





    @property({ type: Node, displayName: "手的位置" })
    protected arrowInHand: Node = null!//手里拿的箭

    @property({ type: Number, displayName: "普通攻击速度" })
    protected attackSpeed: number = 2//玩家攻击速度（普通攻击）
    @property({ type: Number, displayName: "普通攻击范围" })
    protected attickFanwei: number = 25

    public nowEnemy: Node = null  //当前敌人
    public warmingNode: Node = null//技能范围

    protected isJiansu: boolean = false
    public isWuDI: boolean = false

    protected myConfig: any = null
    protected _nowCameraWorPos: Vec3 = new Vec3()
    protected _offsetY: number = 0
    protected _camer: Node = null
    protected enemy_root: Node = null!//敌人根节点
    protected _ndRunSmokeEffect: Node = null!;//烟雾特效
    private _isDie: boolean = false//玩家死亡
    public isStopAllAni: boolean = false//停止播放所有动画
    public set isDie(v: boolean) {
        this._isDie = v;
    }

    public get isDie(): boolean {
        return this._isDie
    }
    protected _degree: number = 0

    protected get degree(): number {
        return this._degree
    }


    protected set degree(v: number) {
        this._degree = v;
    }

    protected PlayerModel: PlayerModel = null
    protected body: RigidBody = null
    protected dir: Vec3 = new Vec3()



    protected isMove: boolean = false//玩家是否还在移动
    protected isLookAt: boolean = false//人物朝向敌人
    protected onlyRotate: boolean = false//只旋转

    protected isStopMove: boolean = false//摇杆直接作废

    protected skillPos: Vec3 = new Vec3()//范围技能释放时候记录坐标

    protected skillForward: Vec3 = new Vec3()//激光类型技能的朝向


    protected scriptBloodBar: MonsterBloodBar = null
    protected bloodBar: Node = null;

    public totalHP: number = 0

    protected oldSpeen: number = 0
    /**
* 展示小怪血条
*  
* @param {*} scriptParent 
* @param {number} totalBlood
* @param {number} bloodBarType
* @param {Function} [callback=()=>{}]
* @param {Vec3} [offsetPos=MONSTER_BLOOD_OFFSET_POS]
* @param {Vec3} [scale=MONSTER_BLOOD_SCALE]
* @memberof uiManager
*/
    protected showPlayerBloodBar(totalBlood: number, callback: Function = () => { }, offsetPos: Vec3 = v3_monsterBloodOffsetPos, scale: Vec3 = v3_monsterBloodScale) {
        // console.log();
        if (!this.bloodBar) {
            this.bloodBar = poolManager.instance.getNode(ResMgr.Instance.getAsset("GUI", "fight/playerBloodBar"), GameApp.Instance.bloodBar_root);




        }
        if (!this.scriptBloodBar) {

            this.scriptBloodBar = this.bloodBar.getComponent(MonsterBloodBar) as MonsterBloodBar;

        }
        let pos = GameApp.Instance.Camera.node.getComponent(CameraComponent).convertToUINode(this.node.worldPosition, find('Canvas') as Node) as Vec3;
        pos.add(offsetPos);
        this.bloodBar.setPosition(0, 0, 0)
        this.bloodBar.setScale(v3_monsterBloodScale)
        this.scriptBloodBar.show(this, totalBlood, offsetPos, scale, callback);
        // console.log(GameApp.Instance.bloodBar_root);





    }
    public fuhuo() {
        SoundMgr.Instance.playSound(ResMgr.Instance.getAsset("Sounds", "revive"))
        this.isDie = false
        this.isMove = true
        this.isStopMove = false
        this.isWuDI = true
        this.isStopAllAni = false
        const hp: number = this.totalHP / 2
        const sub: number = this.totalHP - hp
        this.hp = hp
        this.bloodBar = null
        this.scriptBloodBar = null
        this.showPlayerBloodBar(this.totalHP)
        this.scriptBloodBar.refreshBlood(-sub)
        this.PlayerModel.playAni(this.idelAni)

        const effect: Node = poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "effect/revival"), this.node)

        myUtil.playEffect(effect, false, true, 1, true, 0, () => {
            //播放完复活动画播放背景音乐
            SoundMgr.Instance.stopBgMusic()
            SoundMgr.Instance.playBgMusic(ResMgr.Instance.getAsset("Sounds", "bgm2"), true)
        })
        //无敌5秒
        let time: number = TimerMgr.Instance.ScheduleOnce(() => {
            try {
                if(time){
                    TimerMgr.Instance.UnSchedule(time)
                    time = null
                }
    
                    if (this.node) {
                        
                   
                        this.isWuDI = false
                    }
            } catch (error) {
                  console.error("复活无敌计时器删除失败");
                  
            }
  

            
   
        }, this, 5)

    }

    //显示技能圈
    public showWarming(type: RangeType, skillName: string) {
        this.warmingNode = null
        switch (type) {
            case RangeType.Circle:
                //    console.log("生成圆形");
                this.warmingNode = poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "warming/Circle"), GameApp.Instance.wrramingRoot)

                break;


            case RangeType.Laser:
                //   console.log("生成激光");
                this.warmingNode = poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "warming/Laser"), GameApp.Instance.wrramingRoot)
                break;

            default:
                break;
        }


        const playerPos: Vec3 = this.node.getWorldPosition()
        this.warmingNode.setWorldPosition(playerPos.x, constant.wrramingY, playerPos.z)

    }


    //给弓箭手加弓箭
    public up_arrowInHand() {
        let _ndBody: Node = this.arrowInHand.getChildByName("body").getChildByName("effects") as Node;
        _ndBody.destroyAllChildren()
        if (GameApp.Instance.trailName != "") {
            poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "arrowEffects/" + GameApp.Instance.trailName), _ndBody)

        }
    }
    public hidWarming() {
        if (this.warmingNode) {
            switch (this.warmingNode.name) {
                case "Circle":
                    this.skillPos = this.warmingNode.getChildByName("ball").worldPosition
                    break;
                case "Laser":
                    this.skillForward = this.warmingNode.forward
                    break;
                default:
                    break;
            }
            poolManager.instance.putNode(this.warmingNode)
            this.warmingNode = null
        }




    }
    //找敌人
    protected findEnemy(): Node {

        var nodeArr = []
        const enemyArr = this.enemy_root.children

        for (let i = 0; i < enemyArr.length; i++) {
            const len: number = myUtil.getTwoNodeXZLengthSqr(enemyArr[i], this.node)

            if (len <= this.attickFanwei) {
                nodeArr.push(enemyArr[i])

            }
        }


        return this.getNearestMonster(nodeArr)
    }


    /**
     * 获取距离最近的小怪、boss节点
     * @returns 
     */
    protected getNearestMonster(enemyArr: Node[]) {


        if (enemyArr.length) {
            let arr = enemyArr.sort((a: any, b: any) => {
                let distanceA = myUtil.getTwoNodeXZLengthSqr(this.node, a);
                let distanceB = myUtil.getTwoNodeXZLengthSqr(this.node, b);
                return distanceA - distanceB;
            })

            arr = arr.filter((item: Node) => {
                let ts: enemyBase = null

                ts = item.getComponent(enemyBase);



                return item.parent !== null && ts && !ts.isDie
            })

            return arr[0];
        } else {
            return null;
        }
    }

    public addHp() {
        const effect: Node = poolManager.instance.getNode(ResMgr.Instance.getAsset("prefab", "effect/recovery"), this.node)

        myUtil.playEffect(effect, false, true, 1, true, 0, () => {
            const add: number = this.totalHP * 0.2
            if (this.scriptBloodBar) {
                this.scriptBloodBar.refreshBlood(add)

            }
        })
 
    }
    public init() {
        this.isDie = false
        this.isMove = false
        this.isStopMove = false
        this.isStopAllAni = false
        this.isJiansu = false
        this.mSpeed += this.oldSpeen *= (GameApp.Instance.playerData.minjie / 100)//设置移动速度
        //  console.log("我的移动",this.mSpeed);

        this._camer = GameApp.Instance.Camera.node
        this._nowCameraWorPos = this._camer.eulerAngles
        this._offsetY = this._nowCameraWorPos.y
        this.enemy_root = GameApp.Instance.enemyRoot
        this.attickFanwei *= this.attickFanwei


        this.hp = GameApp.Instance.playerData.shengming
      //  console.log("玩家血" + this.hp);



        //先计算下血量
        this.totalHP = this.hp;
        this.showPlayerBloodBar(this.totalHP)

    }

    public die() {
        if (this._isDie) {
            return
        }
        if (GameApp.Instance.isGameOver) {

            return
        }
        SoundMgr.Instance.stopBgMusic()
        poolManager.instance.putNode(this.bloodBar)
        this.bloodBar = null
        this.scriptBloodBar = null
        this._isDie = true

        this.PlayerModel.playAni(this.dieAni, false, () => {
            this.isStopAllAni = true
            UIMgr.Instance.IE_ShowUIView("GameOver")
        })



        // 
    }

    //玩家受到攻击
    public hit(num: number, howHit: Node) {
        
        if (GameApp.Instance.isGameOver) {
            return
        }



        //统一在这里计算伤害
        if (this._isDie || this.isWuDI) {
            return
        }
        if (howHit.getComponent(enemyBase)) {
            if (howHit.getComponent(enemyBase).obj_type == OBJ_TYPE.friendly) {


                return
            }
        }
        let hitNum: number = num
        

        hitNum = hitNum + (hitNum * constant.enemyAttack * GameApp.Instance.level)
   
        if (GameApp.Instance.playerData.fangyu > 0) {
            let fangyu: number = GameApp.Instance.playerData.fangyu / 100
             //防御最多不超过0.4
            if(fangyu>=1){
                fangyu=0.4
            }

         
            const sub: number = hitNum * fangyu
    
            

            hitNum -= sub
        

        }
        if (hitNum == 0) {

            return
        }
   
        this.hp -= hitNum
        if (this.hp < 0) {
            this.hp = 0
        }



        this.scriptBloodBar.refreshBlood(-hitNum)
        if (this.hp <= 0) {
            this.die()

        }







    }
    onLoad() {
        //    this.mSpeed/=10
        this.body = this.node.getComponent(RigidBody)
        this.PlayerModel = this.node.getChildByName("body").getComponent(PlayerModel)
        this.oldSpeen = this.mSpeed//基类起始速度
        //  console.log(this.PlayerModel);
        //  console.log(this.body);
        EventMgr.Instance.AddEventListener(constant.EVENT_NAME.isMove, this.isMove_callBack, this)

    }
    onDestroy() {
        EventMgr.Instance.RemoveEventListener(constant.EVENT_NAME.isMove, this.isMove_callBack, this)

    }
    onDisable() {


    }
    onEnable() {



    }
    //攻击动画回调
    public attickCallback() { }//自动攻击
    public attickEnemy() { }//自动攻击
    private isMove_callBack(name: string, data: {}) {
        if (this.isStopMove || this.isDie) {


            this.isMove = false
            // this.PlayerModel.stopAni()
            // this.PlayerModel.playAni("idle", true, null)
            this.dir = Vec3.ZERO
            return
        }

        // if (GameApp.Instance.isSetAttr) {
        //     this.dir = Vec3.ZERO
        //     return
        // }

        if (!data["isMove"]) {
            // this.hideRunSmoke()
            this.isMove = false
            this.PlayerModel.playAni(this.idelAni, true, null)
            this.dir = Vec3.ZERO
            this.attickEnemy()//自动攻击敌人
            return
        } else {
            //this.playRunSmoke()

            this.isLookAt = false

            this.isMove = true



            this._degree = data["degree"] - 90//摇杆传过来的角度
            this._degree += this._offsetY


            var r: number = this._degree / 180 * Math.PI
            var x: number = Math.cos(r)
            var y: number = Math.sin(r)
            this.dir = new Vec3(-y, x, 0)




            this.PlayerModel.playAni(this.walkAni, true, null)
        }



    }

    start() {

    }
    //四元数插值旋转
    private rotateNode(n: Node, r: number, t: number) {
        //旋转 可封装
        let now: Quat = new Quat()
        let dstRot: Quat = new Quat()
        const Euler: Vec3 = new Vec3(0, r, 0)//欧拉旋转
        Quat.fromEuler(dstRot, Euler.x, Euler.y, Euler.z)//新的朝向
        // 四元数得球面插值;  
        Quat.slerp(now, n.getRotation(), dstRot, t);
        n.setRotation(now);
    }

    protected skillRotat(dt) {
        this.rotateNode(this.node, this._degree, dt * 0.2)
    }
    private movePlayer(dt: number) {


        if (this.dir == Vec3.ZERO) {
            this.body.setLinearVelocity(Vec3.ZERO)


            return
        }









        //技能跟人物角度旋转 类似激光技能
        if (this.onlyRotate) {
            //激光技能
            this.body.setLinearVelocity(Vec3.ZERO)
            this.skillRotat(dt)



        } else {
            //技能预警跟着人物走
            if (this.warmingNode) {
                this.warmingNode.setWorldPosition(this.node.worldPosition.x, constant.wrramingY, this.node.worldPosition.z)


            }


            this.rotateNode(this.node, this._degree, 10 * dt)

            const Speed_pos: Vec3 = new Vec3(this.dir.x * this.mSpeed * dt, 0, -this.dir.y * this.mSpeed * dt)
            this.body.setLinearVelocity(Speed_pos)
        }



    }
    update(dt: number) {

        if (this._isDie) {
            this.body.setLinearVelocity(Vec3.ZERO)
            this.onlyRotate = false
            this.isStopMove = true
            this.isMove = false
            this.isLookAt = false
            return
        }




        //朝向目标 一般是释放技能时候调用
        if (this.isLookAt) {
            //可封装
            this.body.setLinearVelocity(Vec3.ZERO)
            const old: Vec3 = this.node.eulerAngles.clone()
            if (this.nowEnemy) {
                this.node.lookAt(this.nowEnemy.worldPosition)
            }

            this._degree = this.node.eulerAngles.y
            this.node.setRotationFromEuler(old)

            this.rotateNode(this.node, this._degree, 10 * dt)


        } else {
            //移动玩家
            this.movePlayer(dt)
        }


    }
}


